home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-04-18 | 33.6 KB | 1,221 lines | [TEXT/MMCC] |
- //---------------------------------------------------------------------
- //---------------------------------------------------------------------
- //
- // Horrible Rickety Shell, by Dave Johnson
- //
- // © Copyright 1985 - 1995 Anyone Who Wants It,
- // All Rights Energetically Hurled as far away from me as possible.
- // Use at your own (considerable) risk.
-
-
- #include "PaperJuggling.h"
- #include "DialogUtils.h"
- #include <CodeFragments.h>
-
- // Shell globals we need
- extern Boolean doneflag;
- extern MenuHandle gShellMenuHandles[];
- extern short gDocTitleHeight, gDocFrameWidth; // Window Stats, for use in positioning
- extern GXPrintingEventUPP gOurPrintingOverrideUPP;
-
- // Dialog UPPs
- extern UserItemUPP gBtnOutlineUPP;
- extern ModalFilterUPP gStdKeyFilterUPP, gNumFilterUPP;
-
- // temp prototype
- void CreateSampleImage(WindowPtr wind);
-
- /* These are stolen from arith.c, so we don't have to include the ANSI library for
- 2 routines
- int
- abs(int i)
- {
- if (i < 0)
- return(-i);
- return(i);
- }
-
-
- long
- labs(long i)
- {
- if (i < 0)
- return(-i);
- return(i);
- }
- */
-
- /****************************************************
- Quickdraw Things...
- *****************************************************/
-
- /*------------------------------------------------------------------------
- NewPixImage() Creates pix image and inits the fields of the pixmap...
- ------------------------------------------------------------------------*/
-
- Boolean NewPixImage(PixMapHandle ThePix, Rect *TheRect, short dpth)
- {
- Ptr ThePtr;
- long Offrowbytes, ptrsize;
-
- Offrowbytes =(((dpth * (TheRect->right - TheRect->left)) + 15) / 16) * 2;
- ptrsize = (TheRect->bottom - TheRect->top) * Offrowbytes;
- ThePtr = NewPtr(ptrsize);
- if(MemError() != noErr)
- return(false);
-
- (**ThePix).baseAddr = ThePtr;
- (**ThePix).rowBytes = Offrowbytes + 0x8000;
- (**ThePix).bounds = *TheRect;
- (**ThePix).pixelSize = dpth;
- (**ThePix).cmpCount = 1;
- (**ThePix).cmpSize = dpth;
- return(true);
- }
-
-
- /*------------------------------------------------------------------------
- NewBitMap() Creates bit image and inits the fields of the bitmap...
- ------------------------------------------------------------------------*/
-
- Boolean NewBitMap(BitMap *TheMap, Rect *TheRect)
- {
- long rb;
- Ptr ba;
-
- rb = ((TheRect->right - TheRect->left + 15) / 16) * 2;
- ba = NewPtr(rb * (TheRect->bottom - TheRect->top));
- if( MemError() == noErr)
- {
- TheMap->rowBytes = rb;
- TheMap->baseAddr = ba;
- TheMap->bounds = *TheRect;
- return(true);
- }
- else
- return(false);
- }
-
- /*-------------------------------------------------------------------------
- CenterRect() Centers theRect over thePt...
- --------------------------------------------------------------------------*/
- void CenterRect(Rect *theRect, Point *thePt)
- {
- // First home theRect...
-
- OffsetRect(theRect, -theRect->left, -theRect->top);
-
- // ...then center it over thePt
-
-
- thePt->h = thePt->h - (theRect->right / 2);
- thePt->v = thePt->v - (theRect->bottom / 2);
- OffsetRect(theRect, thePt->h, thePt->v);
- }
-
- /*-------------------------------------------------------------------------
- Center() Returns the center of the rect
- --------------------------------------------------------------------------*/
- Point Center(Rect *theRect)
- {
- Point pt;
-
- pt.h = theRect->left + ((theRect->right - theRect->left) / 2);
- pt.v = theRect->top + ((theRect->bottom - theRect->top) / 2);
- return(pt);
- }
-
-
- /*-------------------------------------------------------------------------
- These routines are from DTS Utilities
- --------------------------------------------------------------------------*/
- short NumToolboxTraps(void)
- {
- if (NGetTrapAddress(_InitGraf, ToolTrap) == NGetTrapAddress(0xAA6E, ToolTrap))
- return (0x200);
- else
- return (0x400);
- }
-
- TrapType GetTrapType(short theTrap)
- {
- // OS traps start with A0, Tool with A8 or AA.
- if ((theTrap & 0x0800) == 0) // per D.A.
- return (OSTrap);
- else
- return (ToolTrap);
- }
-
- Boolean TrapAvailable(short theTrap)
- {
- TrapType theTrapType;
-
- theTrapType = GetTrapType(theTrap);
- if ((theTrapType == ToolTrap) && ((theTrap &= 0x07FF) >= NumToolboxTraps()))
- theTrap = _Unimplemented;
-
- return (NGetTrapAddress(_Unimplemented, ToolTrap) != NGetTrapAddress(theTrap,
- theTrapType));
- }
-
- // Catenate 2 Str255s
- void pcat255(StringPtr d, StringPtr s)
- {
- short i, j;
-
- if (((j = s[0]) + d[0]) > 255)
- j = 255 - d[0];
- // Limit dest string to 255.
-
- for (i = 0; i < j;) d[++d[0]] = s[++i];
- }
-
- // Catenate 2 Str63s
- void pcat63(StringPtr d, StringPtr s)
- {
- short i, j;
-
- if (((j = s[0]) + d[0]) > 63)
- j = 63 - d[0];
- // Limit dest string to 63.
-
- for (i = 0; i < j;) d[++d[0]] = s[++i];
- }
-
- // Catenate 2 Strs, but make the result <= 31 characters, with s guaranteed to
- // be at the end
- void AppendStr31(StringPtr d, StringPtr s)
- {
- short i, addLength = s[0], posIndex = d[0];
-
- // Keep suffix a reasonable length
- if(addLength > 20)
- addLength = 20;
-
- // Limit ending srting to 31
- if ((posIndex + addLength) > 31)
- posIndex = 31 - addLength;
-
- // Append
- for (i = 0; i < addLength;) d[++posIndex] = s[++i];
- d[0] = posIndex; // remember new length
- }
-
- /* This routine concatenates 2 pascal strings, adding a space between if addSpace is true */
- char *PStrCat(Str255 str1, Str255 str2, Boolean addSpace)
- {
- unsigned char len1, len2, total;
-
- // check lengths
- len1 = str1[0];
- len2 = str2[0];
- total = len1 + len2 + (addSpace ? 1 : 0);
- if(total > 255)
- return nil;
-
- if(addSpace)
- {
- str1[len1 + 1] = 0x20; // Add the space
- len1 += 1;
- }
- BlockMove(&str2[1], &str1[len1 + 1], (long)len2);
- str1[0] = total;
- return (char *)str1;
- }
-
- // Just copies one string into another
- void PStrCopy(Str255 src, Str255 dst)
- {
- BlockMove(src, dst, (long)(src[0] + 1));
- }
-
- /*---------------------------------------------------------------------------
- Scroll Bar routines: Mostly stolen from TESample, but heavily modified,
- so even their mother wouldn't know 'em.
- ---------------------------------------------------------------------------*/
-
- /* Here we resize the scrollbars (if needed) and adjust their values. It's a good
- idea to hide the controls before calling this routine, otherwise
- it'll probably be pretty ugly for the user */
- void AdjustScrollbars(WindowPtr wind, Boolean needsResize)
- {
- DocHandle doc;
-
- doc = GetWindowDoc(wind);
- if(doc == nil)
- return;
-
- // First move and resize the bars, if needed
- if ( needsResize )
- {
- /* First the horizontal one. Scroll bars actually hang over the edge of the
- window by one pixel, for some sick reason known only to the people who invented
- it. */
-
- MoveControl((*doc)->hScroll, -1, wind->portRect.bottom - kScrollAdjust);
- SizeControl((*doc)->hScroll, (wind->portRect.right -
- wind->portRect.left) - (kScrollAdjust - kScrollTweak),
- kScrollWidth);
-
- // Now the vertical one
- MoveControl((*doc)->vScroll, wind->portRect.right - kScrollAdjust, -1);
- SizeControl((*doc)->vScroll, kScrollWidth, (wind->portRect.bottom -
- wind->portRect.top) - (kScrollAdjust - kScrollTweak));
- }
-
- // Now adjust the values of the scrollbars
- AdjustScrollValues(wind);
- }
-
- // Adjusts the values of the scroll bars.
- void AdjustScrollValues(WindowPtr wind)
- {
- short docSize, max;
- short oldValue, hScroll = 0, vScroll = 0;
- Rect viewRect;
- DocHandle doc;
-
- doc = GetWindowDoc(wind);
- if(doc == nil)
- return;
-
- // viewRect is the port of the window minus the scrollbars
- viewRect = wind->portRect;
- viewRect.right -= kScrollAdjust;
- viewRect.bottom -= kScrollAdjust;
-
- // First Vertical
- oldValue = GetCtlValue((*doc)->vScroll);
- docSize = (*doc)->contentSize.v;
-
- // max is the amount of the picture that can't be seen
- max = docSize - viewRect.bottom;
- if ( max < 0 ) max = 0;
- SetCtlMax((*doc)->vScroll, max);
-
- /* Adjust scroll value if necessary. It's necessary only if the current control
- value (which is also the number of lines scrolled off the top) is greater
- than the control max. If so, then just set the control value to the max,
- i.e. scrolled all the way down. */
- if(oldValue > max)
- {
- SetCtlValue((*doc)->vScroll, max);
- vScroll = oldValue - max;
- }
-
- // Now Horizontal
- oldValue = GetCtlValue((*doc)->hScroll);
- // lines is the number of horiz. pixels in the offscreen world
- docSize = (*doc)->contentSize.h;
- // max is the amount of the picture that can't be seen
- max = docSize - viewRect.right;
- if ( max < 0 ) max = 0;
- SetCtlMax((*doc)->hScroll, max);
-
- /* Adjust scroll value if necessary. It's necessary only if the current control
- value (which is also the number of lines scrolled off the left) is greater
- than the control max. If so, then just set the control value to the max,
- i.e. scrolled all the way right. */
- if(oldValue > max)
- {
- SetCtlValue((*doc)->hScroll, max);
- hScroll = oldValue - max;
- }
-
- if(hScroll != 0 || vScroll != 0)
- DoScroll(wind, hScroll, vScroll, true);
- }
-
-
-
- /* Determines how much to change the value of the scrollbar by and how
- much to scroll the content, and then does both */
- pascal void ScrollActionProc(ControlHandle control, short part)
- {
- short amount, value, max;
- WindowPtr wind;
-
- if ( part != 0 ) { // if it was actually in the control
- wind = (*control)->contrlOwner;
- switch ( part ) {
- case inUpButton:
- case inDownButton: // one line
- amount = kLineScrollAmount;
- break;
- case inPageUp: // one page
- case inPageDown:
- amount = kPageScrollAmount;
- break;
- }
- if ( (part == inDownButton) || (part == inPageDown) )
- amount = -amount; // reverse direction for a downer
-
- /* Pin the amount to the scroll bar range, set the value, and calculate the
- change in value */
- value = GetCtlValue(control); // get current value
- max = GetCtlMax(control); // and maximum value
- amount = value - amount;
- if ( amount < 0 )
- amount = 0;
- else if ( amount > max )
- amount = max;
- SetCtlValue(control, amount);
- amount = value - amount; // calculate the real change
-
- // Scroll the content the appropriate amount
- if ( amount != 0 )
- {
- DocHandle doc;
-
- doc = GetWindowDoc(wind);
-
- if(control == ((*doc)->hScroll))
- DoScroll(wind, amount, 0, true);
- else
- DoScroll(wind, 0, amount, true);
- }
- }
- } // ScrollActionProc
-
- // Adds 2 scroll bars to the given window, adjusting them to fit
- Boolean AddStdScrollBars(WindowPtr wind)
- {
- ControlHandle scrollHandle;
- Rect scrollRect;
- short min, max;
- Boolean rslt = false;
- DocHandle doc;
-
- doc = GetWindowDoc(wind);
- if(doc == nil)
- return false;
-
- /* These are just dummy values for the rect and the min and max. They will be
- adjusted in the AdjustScrollBars routine */
-
- // First the horizontal one
- SetRect(&scrollRect, 0, 0, 10, 10);
- min = 0;
- max = 10;
- scrollHandle = NewControl(wind, &scrollRect, "\p", false,
- min, min, max, scrollBarProc, 0);
-
- if(scrollHandle != nil)
- {
- // Stash it in the document
- (*doc)->hScroll = scrollHandle;
-
- // Now the vertical
- scrollHandle = NewControl(wind, &scrollRect, "\p", false,
- min, min, max, scrollBarProc, 0);
- if(scrollHandle != nil)
- {
- // Stash it in the document
- (*doc)->vScroll = scrollHandle;
- rslt = true;
- }
- else
- DisposeControl((*doc)->hScroll);
- }
- if(rslt == true)
- {
- // Set up the scroll bars for the current world
- AdjustScrollbars(wind, true);
- }
- return rslt;
- }
-
- OSErr InitStdDoc(WindowPtr wind)
- {
- DocHandle doc;
- OSErr err = -1;
-
- doc = GetWindowDoc(wind);
- if(doc == nil)
- return -1;
-
- // Add scroll bars
- if(AddStdScrollBars(wind))
- {
- // Init the GX stuff
- err = AddWindowGXStuff(wind);
- if(err == noErr)
- {
- // clear the dirty flag
- (*doc)->dirty = false;
-
- // These numbers are random: the app will put in real values
- (*doc)->contentSize.h = 144;
- (*doc)->contentSize.v = 144;
- }
- }
- return err;
- }
-
- Boolean CheckMachine(void)
- {
- short err, rslt = true;
- long gestResult;
-
- // Check the machine's capabilities to be sure we can run
-
- // Check for availability of Gestalt
- if(!TrapAvailable(_Gestalt))
- return false;
-
- // Check for availability of GWorlds
- err = Gestalt(gestaltQuickdrawVersion, &gestResult);
- if(err != noErr)
- return false;
- if(gestResult < 0x0200) // no 32-bit QD
- return false;
-
- // Check for availability of FSSpec file routines
- err = Gestalt(gestaltFSAttr, &gestResult);
- if(err != noErr)
- return false;
- if((gestResult & (1 << gestaltHasFSSpecCalls)) == 0)
- return false;
-
- // Check for availability of Standard Get/Put routines
- err = Gestalt(gestaltStandardFileAttr, &gestResult);
- if(err != noErr)
- return false;
- if((gestResult & (1 << gestaltStandardFile58)) == 0)
- return false;
-
- // Check for availability of FindFolder routine
- err = Gestalt(gestaltFindFolderAttr, &gestResult);
- if(err != noErr)
- return false;
- if((gestResult & (1 << gestaltFindFolderPresent)) == 0)
- return false;
-
- // Check for availability of TempMem routines
- err = Gestalt(gestaltOSAttr, &gestResult);
- if(err != noErr)
- return false;
- if((gestResult & (1 << gestaltTempMemSupport)) == 0)
- return false;
-
- // Check for Apple Event Manager
- err = Gestalt(gestaltAppleEventsAttr, &gestResult);
- if( err != noErr || !(gestResult & (1L >> gestaltAppleEventsPresent)) )
- return false;
-
- return true;
- }
-
- /* This routine calculates a document window's title bar height and frame width, for
- later use in positioning and growing windows. (Did you know that GrowWindow() takes
- as limits the size of the window's strucRgn, but returns the size of its portRect?) */
- void CalcWindowStats(void)
- {
- WindowRecord tempWind;
- Rect globalPortRect, strucRect, offScreenRect, deskRect;
-
- // Make a small rectangle that is off the screen
- deskRect = (**GetGrayRgn()).rgnBBox;
- SetRect(&offScreenRect, 0, 0, 32, 32);
- OffsetRect(&offScreenRect, deskRect.left - 64, 0);
-
- /* Make a visible window that the user can't see. Only when a window is visible
- can you find out its strucRgn dimensions */
- NewWindow(&tempWind, &offScreenRect, "\p", true, documentProc, (WindowPtr)-1, false, 0);
-
- /* OK, we have a window. Now calculate the info we need. First we need
- to globalize the portRect and get the strucRect of the window */
- globalPortRect = ((GrafPtr)(&tempWind))->portRect;
- SetPort((GrafPtr)&tempWind);
- LocalToGlobal(&topLeft(globalPortRect));
- LocalToGlobal(&botRight(globalPortRect));
- strucRect = (*(((WindowPeek)(&tempWind))->strucRgn))->rgnBBox;
-
- /* Calculate the window's title bar height. I'm not entirely sure why you need to
- subtract 1 here, but Craig Prouse did it in his Window Zoom routine, and I'm sure
- he had a good reason for it, so I'll do it too. */
- gDocTitleHeight = globalPortRect.top - 1 - strucRect.top;
-
- // Calculate the width of the window's right side frame
- gDocFrameWidth = strucRect.right - 1 - globalPortRect.right;
-
- // All Done, kill the window
- CloseWindow((WindowPtr)&tempWind);
- }
-
- // Get the document out of the window
- DocHandle GetWindowDoc(WindowPtr wind)
- {
- DocHandle doc = nil;
-
- if ( wind != nil && IsAppWindow(wind) )
- doc = (DocHandle) GetWRefCon(wind);
-
- return doc;
- }
-
- // Returns true if the given window is user kind and not nil
- Boolean IsAppWindow (WindowPtr wind)
- {
- return ((((WindowPeek) wind)->windowKind == userKind) && (wind != nil));
- }
-
- /* This routine gets any pending activate and update events from the queue and processes
- them. Used when saving changes, when a window is brought to the front behind a dialog */
- void DoActivateUpdate(void)
- {
- EventRecord event;
- GrafPtr oldport;
-
- // First do activates
- while(GetNextEvent(activMask, &event) == true)
- {
- AppActivate((WindowPtr)event.message, event.modifiers & activeFlag);
- }
-
- // Then updates
- while(GetNextEvent(updateMask, &event) == true)
- {
- GetPort(&oldport);
- SetPort((WindowPtr)event.message);
- BeginUpdate((WindowPtr)event.message);
-
- AppUpdate((WindowPtr)event.message);
-
- EndUpdate((WindowPtr)event.message);
- SetPort(oldport);
- }
- }
-
-
- /* Stolen from Craig Prouse's famous DoWZoom routine, and modified for my own devious
- purposes. I tried to copy the Finder's behavior: If I can just size the window bigger
- and the result will stay completely on the same device the window is already on, I do
- that. Otherwise the window is zoomed to the top left of the appropriate device. This
- routine assumes up front that we are running in a Color Quickdraw environment, i.e
- there is the possibility of multiple devices. It does NOT zoom the window, it just
- calculates the appropriate rect and installs it in the window's stdState field */
- void ReadyWZoom(WindowPtr wind, short zoomDir, short maxH, short maxV)
- {
- // Only if we are zooming out do we need to go through all these gyrations
- if(zoomDir == inZoomOut)
- {
- Rect globalPortRect, theSect, zoomRect, deviceRect;
- GDHandle nthDevice, dominantGDevice;
- long sectArea, greatestArea;
-
- globalPortRect = wind->portRect;
- LocalToGlobal(&topLeft(globalPortRect));
- LocalToGlobal(&botRight(globalPortRect));
-
- /* Walk the device list looking for the device that contains most of the
- window, or all of the window */
- nthDevice = GetDeviceList();
- greatestArea = 0;
- while(nthDevice != nil)
- {
- SectRect(&globalPortRect, &(*nthDevice)->gdRect, &theSect);
-
- /* if the intersection is equal to the portRect, then the window is fully
- contained on this device: we can stop looking */
- if(EqualRect(&globalPortRect, &theSect))
- {
- dominantGDevice = nthDevice;
- break;
- }
- sectArea = (long)(theSect.right - theSect.left) * (theSect.bottom - theSect.top);
- if(sectArea > greatestArea)
- {
- greatestArea = sectArea;
- dominantGDevice = nthDevice;
- }
- nthDevice = GetNextDevice(nthDevice);
- }
-
- /* Now let's see if we can just increase the window's size to the max and stay
- completely on the dominantGDevice */
- SetRect(&zoomRect, globalPortRect.left, globalPortRect.top,
- globalPortRect.left + maxH, globalPortRect.top + maxV);
- deviceRect = (*dominantGDevice)->gdRect;
- InsetRect(&deviceRect, 4, 4); // Keep window 4 pixels away from edges
- SectRect(&zoomRect, &deviceRect, &theSect);
-
- /* if the intersection is equal to the zoomRect, then the zoomRect is fully
- contained on this device: we have our new zoomRect. Otherwise we need to
- do a little more work. */
- if(!EqualRect(&zoomRect, &theSect))
- {
- short bias;
-
- /* Calculate the height of the window's title bar. Actually, in this app
- I already have, but in the interests of easy cut and paste I'll do
- it again */
- bias = globalPortRect.top - 1 - (*(((WindowPeek)wind)->strucRgn))->rgnBBox.top;
-
- /* Now we can create our zoom rectangle. Account for MBarHeight if on the
- main device */
- if(dominantGDevice == GetMainDevice())
- bias += GetMBarHeight();
- zoomRect.left = deviceRect.left;
- zoomRect.top = deviceRect.top + bias;
-
- /* Set right and bottom to either the max size or the deviceRect,
- whichever is less */
- if(zoomRect.left + maxH > deviceRect.right)
- zoomRect.right = deviceRect.right;
- else
- zoomRect.right = zoomRect.left + maxH;
-
- if(zoomRect.top + maxV > deviceRect.bottom)
- zoomRect.bottom = deviceRect.bottom;
- else
- zoomRect.bottom = zoomRect.top + maxV;
- }
-
- // Load the rect into the stdState of the window
- (*(WStateDataHandle)(((WindowPeek)wind)->dataHandle))->stdState = zoomRect;
- }
- }
-
-
- /* Sets the clip of the window to exclude the scroll bars. Assumes the port is set
- already */
- void CloseClip(WindowPtr wind)
- {
- Rect clip;
-
- clip = wind->portRect;
- clip.right -= kScrollAdjust;
- clip.bottom -= kScrollAdjust;
- ClipRect(&clip);
- }
-
- void DoErrorAlert(short stringID1, short error)
- {
- Str255 string1, string2;
-
- GetIndString(string1, kErrorStringsID, stringID1);
- if(error != 0)
- NumToString((long)error, string2);
- else
- *string2 = 0;
-
- ParamText(string1, string2, "\p", "\p");
- StopAlert(kErrorAlertID, nil);
- }
-
- // Puts up the "Save Changes?" dialog, and returns the number of the button hit
- short SaveChangesDlog(void)
- {
- Str255 fileName;
- DialogPtr dptr;
- short hit, kind;
- Handle itmhndl;
- Rect rect;
- Boolean rslt = false;
-
- #define NOSAVEBUTTON 4
-
- /* Get the title of the front window, and use ParamText to set it in
- the dialog */
- GetWTitle(FrontWindow(), fileName);
- ParamText(fileName, "\p", "\p", "\p");
-
- dptr = GetNewDialog(kSaveChangesDlogID, nil, (WindowPtr)(-1));
- if(dptr == nil)
- {
- DoErrorAlert(kNoResStr, 0);
- return iCancelButton;
- }
-
- // OK button Outline
- GetDItem(dptr, iOKOutline, &kind, &itmhndl, &rect);
- SetDItem(dptr, iOKOutline, userItem, (Handle)gBtnOutlineUPP, &rect);
-
- // Do it...
- ShowWindow(dptr);
- while(true) // Loop until break...
- {
- Boolean out = false;
-
- ModalDialog(gStdKeyFilterUPP, &hit);
- switch(hit)
- {
- case iOKButton:
- case iCancelButton:
- case NOSAVEBUTTON:
- rslt = hit;
- out = true;
- break;
-
- default: // Anything else hit...
- continue;
- }
- if(out)
- break;
- }
- DisposDialog(dptr);
- return rslt;
- }
-
- /* This routine closes all the windows
- It returns true if the caller should proceed, or false if the user canceled along the way. */
- Boolean CloseAllDocs(void)
- {
- Boolean quitting;
- WindowPtr wind;
-
- wind = FrontWindow();
- if(wind == nil)
- return true; // Done
-
- // Loop through all windows
- quitting = true;
- while(quitting == true && wind != nil)
- {
- quitting = DoClose(wind);
- wind = (WindowPtr)((WindowPeek)wind)->nextWindow;
- if(quitting)
- DoActivateUpdate(); // allow windows behind to activate and draw
- }
- return quitting;
- }
-
- /* This routine positions and sizes the window (assumed hidden) appropriately
- for a "new" document and then shows it. The size is assumed to be already
- set up. */
- void SetUpAndShowWindow(WindowPtr wind)
- {
- Rect deviceRect, docRect;
- GDHandle theDevice;
- short horSize, verSize, wTop, wLeft;
- DocHandle doc;
-
- doc = GetWindowDoc(wind);
- if(doc == nil)
- return;
-
- /* Set up a rect on the deepest device that is inset 4 pixels from the edges.
- Note that if it is the Main device we have to take into account the menu bar. */
- deviceRect = (**GetGrayRgn()).rgnBBox; // Get rect of entire desktop
- theDevice = GetMaxDevice(&deviceRect); // Get the deepest device
- deviceRect = (*theDevice)->gdRect; // Get its rect
- InsetRect(&deviceRect, 4, 4); // Leave a 4 pixel border on the edges
- if(theDevice == GetMainDevice()) // Add the menu bar height if the main device
- deviceRect.top += GetMBarHeight();
-
- // Now set up doc rect
- docRect.top = docRect.left = 0;
- docRect.right = (*doc)->contentSize.h;
- docRect.bottom = (*doc)->contentSize.v;
-
- /* OK, Need to add the height of the title bar
- to the vertical coordinate */
- wLeft = deviceRect.left;
- wTop = deviceRect.top + gDocTitleHeight;
- MoveWindow(wind, wLeft, wTop, false);
-
- /* Now calculate a good size for the window. We'd like to make it the full size
- (plus scroll bars), but if it would then hang over the edges of the screen,
- we make it smaller. */
- horSize = docRect.right + kScrollAdjust;
- if(wLeft + horSize > deviceRect.right) // hangs off the right
- horSize = deviceRect.right - wLeft;
- verSize = docRect.bottom + kScrollAdjust;
- if(wTop + verSize > deviceRect.bottom) // hangs off the bottom
- verSize = deviceRect.bottom - wTop;
-
- // Size it, and reset the clip
- SizeWindow(wind, horSize, verSize, false);
- SetPort(wind);
- ClipRect(&wind->portRect);
- ResetGXClip(wind);
-
- // Make sure the scrollbars are presentable
- AdjustScrollbars(wind, true);
-
- // OK, we're ready. Show the window
- ShowWindow(wind);
- }
-
-
- // =====================================================================
- // GX-specific routines
-
- // See if QuickDraw GX is available.If not, return false
- Boolean CheckQuickDrawGX (void)
- {
- long theFeature;
-
- if ( (Gestalt(gestaltGraphicsVersion, &theFeature) != noErr) ||
- (Gestalt(gestaltGXPrintingMgrVersion, &theFeature) != noErr))
- return false; // QuickDraw GX is not available
-
- #ifdef powerc
- // This is a sanity check to see if the PowerPC QuickDrawGXLib is installed.
- // Since we are "weak" linked to QuickDrawGXLib, the Process Manager will
- // launch us even if QuickDrawGXLib is missing. If it's missing, the
- // Code Fragment Manager will leave the address of the functions we call
- // unresolved, and we would crash if we tried to call that function. So,
- // we do a check here and should be prepared to exit gracefully if the
- // library is missing. This could happen if the user has installed a
- // 68K only version of QuickDraw GX. It could also happen if the user has
- // taken the QuickDraw GX extension out of the Extensions Folder.
- //
- // Note - We could check this against any function we call in the library.
- // GXNewGraphicsClient is the first function we call, so it's convenient.
-
- if ( (int)GXNewGraphicsClient == kUnresolvedSymbolAddress )
- return false; // QuickDraw GX is not available in Power Mac
- #endif
-
- return true;
- }
-
- // Get the gxJob out of the window
- gxJob GetWindowGXJob(WindowPtr wind)
- {
- gxJob docJob = nil;
- DocHandle doc = nil;
-
- if ( wind != nil )
- {
- doc = GetWindowDoc(wind);
- if ( doc != nil )
- docJob = (*doc)->docJob;
- }
- return docJob;
- }
-
- // Get the page shape out of the window
- gxShape GetWindowGXShape (WindowPtr wind)
- {
- gxShape docPage = nil;
- DocHandle doc = nil;
-
- if ( wind != nil )
- {
- doc = GetWindowDoc(wind);
- if ( doc != nil )
- docPage = (*doc)->docPage;
- }
- return docPage;
- }
-
- // Get the content port out of the window
- gxViewPort GetWindowGXPort(WindowPtr wind)
- {
- gxViewPort docPort = nil;
- DocHandle doc = nil;
-
- if ( wind != nil )
- {
- doc = GetWindowDoc(wind);
- if ( doc != nil )
- docPort = (*doc)->docPort;
- }
- return docPort;
- }
-
- OSErr AddWindowGXStuff(WindowPtr wind)
- {
- OSErr err;
- DocHandle doc;
- gxJob docJob;
- gxShape docPage;
- gxViewPort docPort, windowPort;
-
- // Attach a default gxViewPort to it
- windowPort = GXNewWindowViewPort(wind);
-
- // Create a print job for this document and save it. This will be the same as the system default until
- // the user goes through the dialogs for Page Setup or Print…
- err = GXNewJob(&docJob);
- if(err == noErr)
- {
- // Now install our application override for PrintingEvent so that we can
- // support the new movable-modal printing dialog boxes.
- GXInstallApplicationOverride(docJob, gxPrintingEvent, gOurPrintingOverrideUPP);
-
- // Create the child view port for scrolling and attach to parent,
- docPort = GXNewViewPort(GXGetViewPortViewGroup(windowPort));
- GXSetViewPortParent(docPort, windowPort);
-
- // Create the page shape. We set the unique items attribute to make sure that each item
- // added to the picture has a unique reference. If this attribute was not set, we would
- // not see all copies of anything we add to the shape multiple times -- we'd just see
- // the last version added.
- docPage = GXNewShape(gxPictureType);
- SetDeepShapeViewPort(docPage, docPort);
- if(docPage != nil)
- {
- doc = GetWindowDoc(wind);
- if(doc != nil)
- {
- (*doc)->docJob = docJob;
- (*doc)->docPage = docPage;
- (*doc)->docPort = docPort;
- }
- }
- else
- err = -108;
- }
- return err;
- }
-
- // This function returns a fixed point rectangle which represents the portRect of the
- // window. The rectangle returned is used as the new clip shape for the content ViewPort.
- void GetGXWindowBounds(WindowPtr wind, gxRectangle *gxRectPtr)
- {
- // Convert the QuickDraw rectangle into a QuickDraw GX fixed point rectangle.
- ShortRectToFixed(&wind->portRect, gxRectPtr);
- }
-
- // resets the clip shape of the content ViewPort after the user has resized the window.
- void ResetGXClip(WindowPtr wind)
- {
- gxRectangle viewRect;
- gxShape clipShape;
- gxViewPort docPort;
-
- // Return a fixed point rectangle in "viewRect" which represents the portRect of the
- // window. This shape will be used as the new clip shape for "gcontentViewPort".
- GetGXWindowBounds(wind, &viewRect);
-
- // Adjust our viewRect to accommodate the scroll bars
- viewRect.right -= ff(kScrollAdjust);
- viewRect.bottom -= ff(kScrollAdjust);
-
- // get the content port
- docPort = GetWindowGXPort(wind);
- if(docPort != nil)
- {
- // Create clip shape, set clip of port, and dispose shape
- clipShape = GXNewRectangle(&viewRect);
- GXSetViewPortClip(docPort, clipShape);
- GXDisposeShape(clipShape);
- }
- }
-
- // This procedure adjusts the mapping of our content viewPort and optionally
- // scrolls the contents of the window
- void DoScroll(WindowPtr wind, short hScroll, short vScroll, Boolean draw)
- {
- Rect scrollRect;
- RgnHandle myRgn;
- gxMapping viewPortMapping;
- gxViewPort docPort;
-
- docPort = GetWindowGXPort(wind);
- if(docPort == nil)
- return;
-
- // The user has scrolled the contents of the window, therefore we need
- // to update the mapping of the content ViewPort to reflect this change.
- GXGetViewPortMapping(docPort, &viewPortMapping);
- MoveMapping(&viewPortMapping, ff(hScroll), ff(vScroll));
- GXSetViewPortMapping(docPort, &viewPortMapping);
-
- if(draw)
- {
- /* Scroll contents of window except for scroll bars */
- scrollRect = wind->portRect;
- scrollRect.right -= kScrollAdjust;
- scrollRect.bottom -= kScrollAdjust;
-
- SetPort(wind);
- myRgn = NewRgn();
- ScrollRect(&scrollRect, hScroll, vScroll, myRgn);
-
- // Add myRgn to the update region and draw
- InvalRgn(myRgn);
- BeginUpdate(wind);
- AppDrawContent(wind);
- EndUpdate(wind);
- DisposeRgn(myRgn);
- }
- }
-
- //--------------------------
- // What follows are all the printing routines from QDGX shell printing.c, renamed
- //------------------------
-
- /**\
- |**| ---------------------------------------------------------------------
- |**| MyPrintingEventOverride()
- |**| Override for GXPrintingEvent. It allows us to update our windows
- |**| when the moveable modal printing dialogs are moved. Keep this in your
- |**| main segment, which will always be loaded when GX tries to call the routine.
- |**| ---------------------------------------------------------------------
- \**/
- OSErr MyGXPrintingEventOverride (EventRecord *event, Boolean filterEvent)
- {
- // Handle events in whatever way is appropriate.
- // MyDoEvent is our generic event handler.
-
- if ( !filterEvent )
- switch(event->what)
- {
- case mouseDown:
- case keyDown:
- case autoKey:
- break;
-
- default:
- DoEvent(event);
- break;
- }
- return noErr;
- }
-
-
- /**\
- |**| ---------------------------------------------------------------------
- |**| SetUpEditMenuRec()
- |**| This routine sets up an gxEditMenuRecord which references our edit
- |**| menu. This structure is used by the GXJobDefaultFormatDialog and
- |**| GXJobPrintDialog calls to allow cut, copy, & paste operations from
- |**| the dialogs.
- |**| ---------------------------------------------------------------------
- \**/
- void SetUpGXEditMenuRec (gxEditMenuRecord *edMenuRec)
- {
-
- edMenuRec->editMenuID = kEditMenuID;
- edMenuRec->cutItem = iCut;
- edMenuRec->copyItem = iCopy;
- edMenuRec->pasteItem = iPaste;
- edMenuRec->clearItem = iClear;
- edMenuRec->undoItem = iUndo;
- }
-
-
- /**\
- |**| ---------------------------------------------------------------------
- |**| DoFormat()
- |**| This routine performs GX's equivalent of the Page Setup (PrStlDialog)
- |**| call of the old printing architecture.
- |**| ---------------------------------------------------------------------
- \**/
- OSErr DoGXFormatDialog (WindowPtr wind, gxDialogResult *result)
- {
- OSErr err = noErr;
- gxEditMenuRecord edMenuRec;
- gxJob docJob;
-
- // If we have a non-nil WindowPtr, set up our edit menu record and handle the job
- // format dialog. Remember to check for errors.
-
- if ( wind != NULL )
- {
- docJob = GetWindowGXJob(wind);
- SetUpGXEditMenuRec(&edMenuRec);
-
- // Un-hilite menu
- HiliteMenu(0);
-
- // Disable the file menu while dialog is up
- DisableItem(gShellMenuHandles[kFileMenu], 0);
-
- *result = GXJobDefaultFormatDialog(docJob, &edMenuRec);
- err = GXGetJobError(docJob);
-
- // Enable the file menu
- EnableItem(gShellMenuHandles[kFileMenu], 0);
- DrawMenuBar();
- }
-
- return err;
- }
-
- /**\
- |**| ---------------------------------------------------------------------
- |**| DoPrinting()
- |**| This routine performs GX's equivalent of the Print Job Dialog
- |**| (PrJobDialog) call of the old printing architecture, and then prints
- |**| the document if the user wants to.
- |**| ---------------------------------------------------------------------
- \**/
- OSErr DoGXPrinting (WindowPtr wind)
- {
- OSErr err = noErr;
- gxDialogResult result;
- gxEditMenuRecord edMenuRec;
- gxJob docJob;
-
- // If we have a non-nil WindowPtr, set up our edit menu record and handle the print
- // job dialog. Remember to check for errors. If no errors occur, and the user clicks
- // ok, print the window's document.
-
- if ( wind != NULL )
- {
- docJob = GetWindowGXJob(wind);
-
- SetUpGXEditMenuRec(&edMenuRec);
-
- // Un-hilite menu
- HiliteMenu(0);
-
- // Disable the file menu while dialog is up
- DisableItem(gShellMenuHandles[kFileMenu], 0);
-
- result = GXJobPrintDialog(docJob, &edMenuRec);
- err = GXGetJobError(docJob);
-
- // Enable the file menu
- EnableItem(gShellMenuHandles[kFileMenu], 0);
- DrawMenuBar();
-
- if ( (result == gxOKSelected) && (err == noErr) )
- err = AppPrintOne(wind);
- }
-
- return err;
- }
-
-
-
- /**\
- |**| ---------------------------------------------------------------------
- |**| DoPrintOne()
- |**| This routine prints one copy of the window's document using whatever
- |**| job and format is currently attached to it. (If the window were just
- |**| created and then the user selected Print One w/o first selecting Page
- |**| Setup…, the system default job and format are stored with this document.
- |**| ---------------------------------------------------------------------
- \**/
- OSErr DoGXPrintOne (WindowPtr wind, gxShape page)
- {
- OSErr err = noErr;
- gxJob docJob;
- Str255 title;
- DocHandle doc;
-
- // If we have a non-nil document, start the print job, print a page and then finish
- // the job. Since we have just a one page document, we don't bother counting pages.
- // Remember to check those errors!
-
- doc = GetWindowDoc(wind);
- if ( doc != nil )
- {
- docJob = (*doc)->docJob;
- GetWTitle(wind, title);
-
- GXStartJob(docJob, title, 1);
- err = GXGetJobError(docJob);
-
- if ( err == noErr )
- {
- GXPrintPage(docJob, 1, GXGetJobFormat(docJob, 1), page);
- err = GXGetJobError(docJob);
- }
-
- GXFinishJob(docJob);
- if ( err == noErr )
- err = GXGetJobError(docJob);
- }
- return err;
- }
-
-
-